#include "dog.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include "string.h"

struct dog_pd_s{
    int weight;
    int age;
};
STATIC_ASSERT(sizeof(struct dog_pd_s) == DOG_PD_SIZE, "file:" __FILE__ " line:" TO_STRING(__LINE__));


static void eat(dog_t v, int bone)
{
    (void)v;
    printf("dog eat %d bones\n", bone);
}

static void get_age(dog_t v)
{
    // 私有变量
    struct dog_pd_s     *pd = (struct dog_pd_s*)GET_PD(v, dog_s);
    printf("dog age: %d\n", pd->age);
}

static void get_weight(dog_t v)
{
    // 私有变量
    struct dog_pd_s     *pd = (struct dog_pd_s*)GET_PD(v, dog_s);
    printf("dog weight: %d\n", pd->weight);
}

// dog要实现自己的run方法, 参数必须与animal的run一样, 或者定义不同的名字, 或者不用匿名结构体
static void dog_run(animal_t v)
{
    dog_t p_dog         = container_of(v, struct dog_s, animal_s_head);         // 根据v找到dog的头部
    struct dog_pd_s *pd = (struct dog_pd_s*)GET_PD(p_dog, dog_s);               // 根据p_dog找到私有变量

    pd->weight--;   // 跑步减肥

    printf("%s :lose weight = %d\n", __FUNCTION__, pd->weight);
}


void dog_destroy(dog_t v)
{
    (void)v;
    printf("%s\n", __FUNCTION__);
    // 其他操作
    memset(v, 0, sizeof(struct dog_s));

}

// 初始化方法和数据, 由DEFINE_DOG调用
// P3: int age
// P4: int weight
void dog_init(dog_t v, int arg_num, ...)
{
    va_list     args;

    animal_init((animal_t)v->animal_s_head, 0);
    v->run = dog_run;   // dog有自己的run方法


    v->dog_init = dog_init;
    v->dog_destroy = dog_destroy;

    v->eat = eat;
    v->get_age = get_age;
    v->get_weight = get_weight;

    va_start(args, arg_num);

    struct dog_pd_s *pd = (struct dog_pd_s*)GET_PD(v, dog_s);
    if (arg_num == 0){
        pd->age = 0;
        pd->weight = 0;
    }else if (arg_num == 1){
        pd->age = va_arg(args, int);
    }else if (arg_num >= 2){
        pd->age = va_arg(args, int);
        pd->weight = va_arg(args, int);
    }

    va_end(args);

}

void dog_cleanup(const void *v)
{
    dog_t p_dog = *(dog_t *)v;      // v是指针的地址, 要用*取值
    printf("v: %p\n", v);
    printf("p_dog: %p\n", p_dog);
    memset((void *)p_dog, 0, sizeof(struct dog_s));
}
